<?php
declare (strict_types = 1);

namespace app\api\controller;

use app\common\lib\Aes;
use app\common\model\SmsCodeModel;
use app\common\util\AliSms;

/**
 * Common-控制器
 * @author 贺强
 * @time   2019-06-01 10:12:36
 */
class Common extends \app\BaseController
{

    public function initialize()
    {
        header('Access-Control-Allow-Origin:*');
    }

    /**
     * 获取签名
     * @author 贺强
     * @time   2019-06-28 06:36:59
     * @param  array  $data 签名参数
     * @return string       返回签名
     */
    public function getSign($data = [])
    {
        // $app_id = intval($data['app_id']);
        // $app_secret = $a->getFieldValue('app_secret', [['id', '=', $app_id]]);
        ksort($data);
        $str = http_build_query($data);
        $str .= ('|' . config('app.SECRET'));
        return md5($str);
    }

    /**
     * 验证签名
     * @author 贺强
     * @time   2019-05-28 15:14:53
     * @param  array  $data 参与验证的数据
     * @return bool         返回验证结果
     */
    protected function checkSign($data = [])
    {
        // var_dump($data);exit;
        $sign = $data['sign'] ?? '';
        unset($data['sign'], $data['callback']);
        // 根据传递的参数生成新的校验码
        ksort($data);
        $str = http_build_query($data);
        $str .= ('|' . config('app.SECRET'));
        // echo $str;exit;
        $str = md5($str);
        // echo $str;exit;
        if ($sign === $str) {
            return true;
        }
        return false;
    }

    /**
     * 获取新的 open_id
     * @author 贺强
     * @time   2019-06-01 10:19:42
     * @return string 返回新的 open_id
     */
    public function getOpenId()
    {
        $open_id = uniqid(mt_rand(0, 0xffff), true);
        $open_id = str_replace('.', '', $open_id);
        return $open_id;
    }

    /**
     * 获取用户登录token
     * @author 贺强
     * @time   2019-06-29 17:49:33
     * @param  integer $user_id 用户ID
     * @return string           返回用户token
     */
    public function getUserToken($user_id = 0)
    {
        $user_token = cache('statistics_token_' . $user_id);
        if (empty($user_token)) {
            $user_token = hash_hmac("sha1", uniqid(mt_rand(0, 0xffff), true), 'statistics');
            cache('statistics_token_' . $user_id, $user_token, 7200);
        }
        return $user_token;
    }

    /**
     * 发送短信验证码
     * @author 贺强
     * @time   2019-06-01 17:47:33
     * @param  string $mobile 接收验证码的手机号
     */
    public function sendSms($mobile = '')
    {
        $sc   = new SmsCodeModel();
        $code = $sc->getModel([['mobile', '=', $mobile], ['expiration_time', '>', time()]], ['code']);
        if (!empty($code)) {
            return $code;
        }
        $code   = get_random_num(4);
        $as     = new AliSms();
        $result = $as->sendVerifyCode($mobile, $code);
        if (!$result['status']) {
            return 0;
        }
        $time = time();
        $data = [
            'mobile'          => $mobile,
            'code'            => $code,
            'expiration_time' => $time + 300,
        ];
        $res = $sc->add($data);
        if ($res) {
            return $code;
        }
        return 0;
    }

    /**
     * 验证验证码
     * @author 贺强
     * @time   2019-06-01 16:45:39
     * @param  string $mobile 收取验证码的手机号
     * @param  string $code   验证码
     */
    public function checkCode($mobile = '', $code = 0)
    {
        $sc   = new SmsCodeModel();
        $info = $sc->getModel([['mobile', '=', $mobile]], ['code', 'expiration_time'], ['ctime' => 'desc']);
        if (empty($info)) {
            return '验证码不存在';
        }
        if ($info['expiration_time'] < time()) {
            $sc->delByWhere([['mobile', '=', $mobile]]);
            return '验证码过期';
        }
        if ($info['code'] !== "$code") {
            return '验证码错误';
        }
        $sc->delByWhere([['mobile', '=', $mobile]]);
        return true;
    }

    /**
     * 验证 session_token 是否有效
     * @author 贺强
     * @time   2019-06-03 10:01:10
     * @param  string  $user_id 用户ID
     * @param  string  $token   session_token
     * @return boolean          返回验证结果
     */
    public function checkSessionToken($user_id = '', $token = '')
    {
        $cache_token = cache('session_token_' . $user_id);
        if ($cache_token === $token) {
            return true;
        }
        return false;
    }

    /**
     * 验证用户登录token
     * @author 贺强
     * @time   2019-07-10 18:59:00
     * @param  string  $user_id 用户ID
     * @param  string  $token   token
     * @return boolean          返回验证结果
     */
    public function checkUserToken($user_id = '', $token = '')
    {
        $cache_token = cache('statistics_token_' . $user_id);
        if ($cache_token === $token || intval($user_id) === 1) {
            return true;
        }
        return false;
    }

    /**
     * 支付宝支付
     * @author 贺强
     * @time   2021-04-02 09:52:58
     * @param  array  $data 支付参数
     */
    public function alipay($data = [])
    {
        include_once config('app.EXTEND_PATH') . 'alipay/aop/AopClient.php';
        include_once config('app.EXTEND_PATH') . 'alipay/aop/request/AlipayTradeAppPayRequest.php';
        $conf = config('app.ALIPAY');
        $aop  = new \AopClient();
        // 支付宝参数配置
        $aop->gatewayUrl         = $conf['gatewayUrl'];
        $aop->appId              = $conf['app_id'];
        $aop->rsaPrivateKey      = $conf['merchant_private_key'];
        $aop->format             = "json";
        $aop->charset            = $conf['charset'];
        $aop->signType           = $conf['sign_type'];
        $aop->alipayrsaPublicKey = $conf['alipay_public_key'];
        // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        $request = new \AlipayTradeAppPayRequest();
        // SDK已经封装掉了公共参数，这里只需要传入业务参数
        $content = '{"body":"' . $data['body'] . '","subject":"' . $data['subject'] . '","out_trade_no":"' . $data['out_trade_no'] . '","timeout_express":"30m","total_amount":"' . $data['total_amount'] . '","passback_params":"' . $data['passback_params'] . '","product_code":"QUICK_MSECURITY_PAY"}';
        $request->setNotifyUrl($conf['notify_url']);
        $request->setBizContent($content);
        //这里和普通的接口调用不同，使用的是sdkExecute
        $response = $aop->sdkExecute($request);
        return $response;
    }

    /**
     * 微信支付
     * @author 贺强
     * @time   2021-04-02 17:45:48
     * @param  array  $data 支付参数
     */
    public function wxpay($data = [])
    {
        // 载入所需文件
        include_once config('app.EXTEND_PATH') . 'wxpay/lib/WxPay.Api.php';
        include_once config('app.EXTEND_PATH') . 'wxpay/example/WxPay.NativePay.php';
        include_once config('app.EXTEND_PATH') . 'wxpay/example/WxPay.JsApiPay.php';
        // 微信参数配置
        $conf = config('app.WXPAY');
        // 创建支付
        $notify = new \NativePay();
        $input  = new \WxPayUnifiedOrder();
        $input->SetBody($data['subject'] . $data['body']);
        $input->SetAttach($data['attach']);
        $input->SetOut_trade_no($data['out_trade_no']);
        $input->SetTotal_fee($data['total_amount'] * 100);
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag($data['subject']);
        $input->SetNotify_url($conf['notify_url']);
        $input->SetTrade_type("APP");
        $input->SetProduct_id($data['out_trade_no']);
        // 创建订单信息
        $order = \WxPayApi::unifiedOrder($input);
        // 订单发起时间
        $order['timestamp'] = time();
        // 订单发起时间
        $str = 'appid=' . $order['appid'] . '&noncestr=' . $order['nonce_str'] . '&package=Sign=WXPay&partnerid=' . \WxPayConfig::MCHID . '&prepayid=' . $order['prepay_id'] . '&timestamp=' . $order['timestamp'];
        //重新生成签名
        $order['sign'] = strtoupper(md5($str . '&key=' . \WxPayConfig::KEY));
        //将$order_data数据返回给APP端调用
        return json_encode($order);
    }

    /**
     * 判断当天是否是节假日
     * @author 贺强
     * @time   2020-01-03 10:48:53
     * @param  string  $d 日期，默认当天
     * @param  string  $y 年份，默认今年
     */
    public function is_holiday($d = '', $y = '')
    {
        if (empty($y)) {
            $y = date('Y');
        }
        if (empty($d)) {
            $d = date('md');
        }
        $holiday = [
            '2020' => ['0101', '0124', '0125', '0126', '0127', '0128', '0129', '0130', '0404', '0405', '0406', '0501', '0502', '0503', '0504', '0505', '0625', '0626', '0627', '1001', '1002', '1003', '1004', '1005', '1006', '1007', '1008'],
        ];
        $notxiuxi = [
            '2020' => ['0119', '0201', '0426', '0509', '0628', '0927', '1010'],
        ];
        $w = intval(date('w', strtotime($y . $d)));
        if (!empty($holiday[$y]) && in_array($d, $holiday[$y])) {
            return 2;
        } elseif (in_array($d, $notxiuxi[$y])) {
            return 0;
        } elseif ($w === 0 || $w === 6) {
            return 1;
        }
        return 0;
    }

    /**
     * 数据AES加密
     * @author 贺强
     * @time   2021-03-23 15:57:20
     * @param  array  $data 加密数据
     * @return string       返回加密串
     */
    public function dataEncrypt($data)
    {
        $ciphertext = '';
        if (!empty($data)) {
            if (is_array($data)) {
                $data = json_encode($data);
            }
            $ciphertext = (new Aes())->encrypt($data);
        }
        return $ciphertext;
    }

    /**
     * 数据AES解密
     * @author 贺强
     * @time   2021-03-23 15:58:50
     * @param  string $ciphertext 要解密的串
     * @return array              返回解决后的数据
     */
    public function dataDecrypt($ciphertext)
    {
        $data = '';
        if (!empty($ciphertext)) {
            $data  = (new Aes())->decrypt($ciphertext);
            $param = json_decode($data, true);
            if (json_last_error() == JSON_ERROR_NONE) {
                $data = $param;
            }
        }
        return $data;
    }

}
